package com.sam.schedule;

import com.sam.bean.JobTaskBuilder;
import com.sam.listener.DataExtractScheduleEvent;
import com.sam.thread.ScheduleHandler;
import com.sam.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean;

@Component
public class ScheduleServiceImpl implements ApplicationListener<DataExtractScheduleEvent> {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @PostConstruct
    public void init(){
        threadPoolTaskScheduler = jobTaskBuilder.buildJobTaskScheduler();
    }

    @Value("${data.extract.isOpen:#{true }}")
    private boolean isOpen;

    //在delay秒后开始调度，每次任务完成后，最少等待period秒后才开始调度下一次任务
    @Value("${data.extract.delay:#{2}}")
    private int delaySecond;

    @Value("${data.extract.period:#{10}}")
    private int periodSecond;

    @Autowired
    private JobTaskBuilder jobTaskBuilder;

    @Autowired
    private ScheduleHandler scheduleHandler;

    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    private ScheduledFuture scheduledFuture;
    private AtomicBoolean isStop = new AtomicBoolean(false);
    private AtomicBoolean isStart = new AtomicBoolean(true);


    public String startJob(){
        logger.info("当前配置: 是否开启调度任务{},{}秒后开始调度任务, 任务完成后，等待{}秒开始调度下一次任务", isOpen, delaySecond, periodSecond);
        if(!isOpen){
            logger.info("未开启调度任务");
            return "未开启调度任务";
        }
        if(isStop.get()){
            logger.info("请先停止当前调度任务");
            return "请先停止当前调度任务";
        }

        if(isStart.get()){
            logger.info("启动调度任务--开始");
            scheduledFuture = threadPoolTaskScheduler.schedule(scheduleHandler, DateUtil.nowAddSeconds(delaySecond));
            isStart.set(false);
            logger.info("启动调度任务--结束");
            return "已启动调度任务";

        } else {
            logger.info("请先停止当前调度任务");
            return "请先停止当前调度任务";
        }

    }

    public String stopJob() {
        logger.info("停止调度任务--开始");
        boolean flag = false;
        try {
            isStop.set(true);
            if (scheduledFuture != null) {
                scheduledFuture.cancel(true);
            }
            scheduleHandler.stopJobRunner();
            threadPoolTaskScheduler.getScheduledThreadPoolExecutor().shutdownNow();
            flag = true;
        } catch (Exception e) {
            logger.error("停止调度任务--异常", e);
        }
        logger.info("停止调度任务--结束");

        return flag ? "停止调度任务成功" : "停止调度任务失败";
    }

    public String reStartJob(){
        if(!isStop.get()){
            logger.info("请先停止当前调度任务");
            return "请先停止当前调度任务";
        }
        logger.info("重启调度任务--开始");
        boolean flag = false;
        try {
            isStop.set(true);
            scheduleHandler.reStart();
            threadPoolTaskScheduler = jobTaskBuilder.buildJobTaskScheduler();
            scheduledFuture = threadPoolTaskScheduler.schedule(scheduleHandler, DateUtil.nowAddSeconds(delaySecond));
            isStop.set(false);
            flag = true;
        } catch (Exception e) {
            logger.error("重启调度任务--异常", e);
        }
        logger.info("重启调度任务--结束");
        logger.info("reStartJob发出调度命令");
        return flag ? "重启调度任务成功" : "重启调度任务失败";
    }

    public Map query(){
        return scheduleHandler.status();
    }



    @Override
    public void onApplicationEvent(DataExtractScheduleEvent dataExtractEvent) {
        logger.info(String.format("第%d次调度任务执行%s",dataExtractEvent.getTotalCount(), statusString(dataExtractEvent.getCode())));
        if(!isStop.get()){
            scheduledFuture = threadPoolTaskScheduler.schedule(scheduleHandler, DateUtil.nowAddSeconds(periodSecond));
            logger.info("onApplicationEvent发出调度命令");
        }

    }

    private String statusString(int code) {
        String s = "未知";
        switch (code) {
            case -1:
                s = "失败";
                break;
            case 0:
                s = "未启动";
                break;
            case 1:
                s = "成功";
                break;
            default :
                s = "运行中";
                break;
        }
        return s;
    }


}
